/*
 *   Copyright 2021 zzh
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */

package com.aduib.boot.web.configure;

import com.aduib.boot.common.json.GsonParser;
import com.aduib.boot.common.json.JacksonParser;
import com.aduib.boot.web.constants.AppConstants;
import com.aduib.boot.web.context.handler.RequestJsonParamHandlerMethodArgumentResolver;
import com.aduib.boot.web.configure.WebProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.Filter;
import java.util.Arrays;
import java.util.List;

/**
 * @description: WebConfig
 * @author: zzh
 * @date: 2021/9/3 10:01
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({WebProperties.class,ProfilesProperties.class})
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
public class AduibWebMvcAutoConfiguration implements WebMvcConfigurer {

  private WebProperties webProperties;

  private ProfilesProperties profilesProperties;

  public AduibWebMvcAutoConfiguration(WebProperties webProperties,
      ProfilesProperties profilesProperties) {
    this.webProperties = webProperties;
    this.profilesProperties = profilesProperties;
  }

  @Bean
  @ConditionalOnClass
  public Gson gson() {
    return GsonParser.GSON;
  }

  @Bean
  @ConditionalOnClass
  public ObjectMapper objectMapper() {
    return JacksonParser.objectMapper;
  }

  /**
   * 跨域配置
   * @return
   */
  @Bean
  public Filter corsFilter(){
    CorsConfiguration corsConfig = new CorsConfiguration();
    List<String> allowedHeaders = Arrays.asList("x-auth-token", "content-type", "X-Requested-With", "XMLHttpRequest");
    List<String> exposedHeaders = Arrays.asList("x-auth-token", "content-type", "X-Requested-With", "XMLHttpRequest");
    List<String> allowedMethods = Arrays.asList("POST", "GET", "DELETE", "PUT", "OPTIONS");
    List<String> allowedOrigins = Arrays.asList("*");
    corsConfig.setAllowedHeaders(allowedHeaders);
    corsConfig.setAllowedMethods(allowedMethods);
    corsConfig.setAllowedOrigins(allowedOrigins);
    corsConfig.setExposedHeaders(exposedHeaders);
    corsConfig.setMaxAge(36000L);
    corsConfig.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
    configSource.registerCorsConfiguration("/**", corsConfig);
    return new CorsFilter(configSource);
  }
  /**
   * 修改默认列表
   *
   * @param converters
   */
  @Override
  public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.removeIf(x->x instanceof MappingJackson2HttpMessageConverter);
    converters.removeIf(x->x instanceof GsonHttpMessageConverter);
    if (AppConstants.JACKSON_TYPE.equals(webProperties.getJsonParserType())) {
      converters.add(0, new MappingJackson2HttpMessageConverter(JacksonParser.objectMapper));
    }
    if (AppConstants.GSON_TYPE.equals(webProperties.getJsonParserType())) {
      converters.add(0,new GsonHttpMessageConverter(GsonParser.GSON));
    }
  }

  /**
   * 会关闭默认列表
   *
   * @param converters
   */
  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  }

  @Override
  public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(new DateTypeConverter());
  }

  @Override
  public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    resolvers.add(new RequestJsonParamHandlerMethodArgumentResolver());
  }
}
